home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / math / ast51src.zip / CHARTS1.C < prev    next >
C/C++ Source or Header  |  1995-12-31  |  45KB  |  1,371 lines

  1. /*
  2. ** Astrolog (Version 5.10) File: charts1.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (Astara@msn.com). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 12/27/1995.
  35. */
  36.  
  37. #include "astrolog.h"
  38.  
  39.  
  40. /*
  41. ******************************************************************************
  42. ** Single Chart Display Routines.
  43. ******************************************************************************
  44. */
  45.  
  46. /* Print the straight listing of planet and house positions and specified */
  47. /* by the -v switch, along with the element table, etc.                   */
  48.  
  49. void ChartListing()
  50. {
  51.   ET et;
  52.   char sz[cchSzDef];
  53.   int i, j, k, fNam, fLoc;
  54.   real rT;
  55.  
  56.   CreateElemTable(&et);
  57.   fNam = *ciMain.nam > chNull; fLoc = *ciMain.loc > chNull;
  58.  
  59.   /* Print header showing time and date of the chart being displayed. */
  60.  
  61.   AnsiColor(kWhite);
  62.   sprintf(sz, "%s %s chart ", szAppName, szVersionCore); PrintSz(sz);
  63.   if (Mon == -1)
  64.     PrintSz("(No time or space)\n");
  65.   else if (us.nRel == rcComposite)
  66.     PrintSz("(Composite)\n");
  67.   else {
  68.     sprintf(sz, "for %s%s", ciMain.nam, fNam ? "\n" : ""); PrintSz(sz);
  69.     j = DayOfWeek(Mon, Day, Yea);
  70.     sprintf(sz, "%c%c%c %s %s (%cT %s GMT)", chDay3(j),
  71.       SzDate(Mon, Day, Yea, 3), SzTim(Tim), ChDst(Dst),
  72.       SzZone(Zon)); PrintSz(sz);
  73.     sprintf(sz, "%c%s%s%s\n", fLoc && !fNam ? '\n' : ' ', ciMain.loc,
  74.       fLoc ? " " : "", SzLocation(Lon, Lat)); PrintSz(sz);
  75.   }
  76.  
  77. #ifdef INTERPRET
  78.   if (us.fInterpret) {          /* Print an interpretation if -I in effect. */
  79.     if (us.nRel == rcSynastry)
  80.       InterpretSynastry();      /* Print synastry interpretaion for -r -I.  */
  81.     else
  82.       InterpretLocation();      /* Do normal interpretation for just -v -I. */
  83.     return;
  84.   }
  85. #endif
  86.  
  87.   AnsiColor(kDkGray);
  88.   if (us.fSeconds) {
  89.     sprintf(sz, "Body  Location   Ret. %s Rul.      House  Rul. Velocity\n",
  90.       us.fEquator ? "Declin. " : "Latitude"); PrintSz(sz);
  91.   } else {
  92.     sprintf(sz,
  93.       "Body  Locat. Ret. %s. Rul.      House  Rul. Veloc.    %s Houses.\n",
  94.       us.fEquator ? "Decl" : "Lati", szSystem[us.nHouseSystem]); PrintSz(sz);
  95.   }
  96.   if (!fNam && !fLoc)
  97.     PrintL();
  98.  
  99.   /* Ok, now print out the location of each object. */
  100.  
  101.   for (i = 1, j = 1; i <= oNorm; i++, j++) {
  102.     if (us.fSeconds) {
  103.       if (ignore[i])
  104.         continue;
  105.     } else {
  106.       if (i > oCore && (i <= cuspHi || ignore[i]))
  107.         continue;
  108.       while (i <= oCore && j <= oCore && ignore[j])
  109.         j++;
  110.     }
  111.     if (i <= oCore && j > oCore)
  112.       PrintTab(' ', 51);
  113.     else {
  114.       if (i > oCore)
  115.         j = i;
  116.       AnsiColor(kObjA[j]);
  117.       sprintf(sz, "%-4.4s: ", szObjName[j]); PrintSz(sz);
  118.       PrintZodiac(planet[j]);
  119.       sprintf(sz, " %c ", ret[j] >= 0.0 ? ' ' : chRet); PrintSz(sz);
  120.       if (j <= cThing || j > cuspHi)
  121.         PrintAltitude(planetalt[j]);
  122.       else
  123.         PrintTab('_', us.fSeconds ? 10 : 7);
  124.       sprintf(sz, " (%c)", Dignify(j, SFromZ(planet[j])));
  125.       PrintSz(FCusp(j) ? "    " : sz);
  126.       k = inhouse[j];
  127.       AnsiColor(kSignA(k));
  128.       sprintf(sz, " [%2d%s house] ", k, szSuffix[k]); PrintSz(sz);
  129.       AnsiColor(kDefault);
  130.       sprintf(sz, "[%c] ", Dignify(j, k)); PrintSz(FCusp(j) ? "    " : sz);
  131.       if ((j != oMoo || us.fPlacalc) &&
  132.         (FObject(j) || ((j == oNod || j == oLil) && us.fPlacalc))) {
  133.         PrintCh((char)(ret[i] < 0.0 ? '-' : '+'));
  134.         rT = DFromR(RAbs(ret[j]));
  135.         sprintf(sz, us.fSeconds ? (rT < 10.0 ? "%9.7f" : "%9.6f") :
  136.           (rT < 10.0 ? "%5.3f" : "%5.2f"), rT); PrintSz(sz);
  137.       } else
  138.         PrintTab('_', us.fSeconds ? 10 : 6);
  139.     }
  140.     if (!us.fSeconds) {
  141.  
  142.       /* For some lines, we have to append the house cusp positions. */
  143.  
  144.       if (i <= cSign) {
  145.         PrintSz("  -  ");
  146.         AnsiColor(kSignA(i));
  147.         sprintf(sz, "House cusp %2d: ", i); PrintSz(sz);
  148.         PrintZodiac(house[i]);
  149.       }
  150.  
  151.       /* For some lines, we have to append the element table information. */
  152.  
  153.       if (i == cSign+2)
  154.         PrintSz("     Car Fix Mut TOT");
  155.       else if (i > cSign+2 && i < cSign+7) {
  156.         k = i-(cSign+2)-1;
  157.         AnsiColor(kElemA[k]);
  158.         sprintf(sz, "  %c%c%c%3d %3d %3d %3d",
  159.           szElem[k][0], szElem[k][1], szElem[k][2],
  160.           et.coElemMode[k][0], et.coElemMode[k][1], et.coElemMode[k][2],
  161.           et.coElem[k]); PrintSz(sz);
  162.         AnsiColor(kDefault);
  163.       } else if (i == cSign+7) {
  164.         sprintf(sz, "  TOT %2d %3d %3d %3d",
  165.           et.coMode[0], et.coMode[1], et.coMode[2], et.coSum); PrintSz(sz);
  166.       } else if (i == oCore)
  167.         PrintTab(' ', 23);
  168.       else if (i >= uranLo) {
  169.         sprintf(sz, "  Uranian #%d", i-uranLo+1); PrintSz(sz);
  170.       }
  171.       sz[0] = chNull;
  172.       switch (i-cSign-1) {
  173.       case 1: sprintf(sz, "   +:%2d", et.coYang);  break;
  174.       case 2: sprintf(sz, "   -:%2d", et.coYin);   break;
  175.       case 3: sprintf(sz, "   M:%2d", et.coMC);    break;
  176.       case 4: sprintf(sz, "   N:%2d", et.coIC);    break;
  177.       case 5: sprintf(sz, "   A:%2d", et.coAsc);   break;
  178.       case 6: sprintf(sz, "   D:%2d", et.coDes);   break;
  179.       case 7: sprintf(sz,    "<:%2d", et.coLearn); break;
  180.       }
  181.       PrintSz(sz);
  182.     } else {
  183.       PrintSz(" Decan: ");
  184.       is.fSeconds = fFalse;
  185.       PrintZodiac(Decan(planet[i]));
  186.       is.fSeconds = us.fSeconds;
  187.     }
  188.     PrintL();
  189.   }
  190.  
  191.   /* Do another loop to print out the stars in their specified order. */
  192.  
  193.   if (us.nStar) for (i = starLo; i <= starHi; i++) if (!ignore[i]) {
  194.     j = oNorm+starname[i-oNorm];
  195.     AnsiColor(kObjA[j]);
  196.     sprintf(sz, "%-4.4s: ", szObjName[j]); PrintSz(sz);
  197.     PrintZodiac(planet[j]);
  198.     PrintSz("   ");
  199.     PrintAltitude(planetalt[j]);
  200.     k = inhouse[j];
  201.     AnsiColor(kSignA(k));
  202.     sprintf(sz, "     [%2d%s house]", k, szSuffix[k]); PrintSz(sz);
  203.     AnsiColor(kDefault);
  204.     sprintf(sz, "     ______%s Star #%2d: %5.2f\n",
  205.       us.fSeconds ? "____" : " ", i-oNorm, rStarBright[j-oNorm]); PrintSz(sz);
  206.   }
  207. }
  208.  
  209.  
  210. /* Print out the aspect and midpoint grid for a chart, as specified with the */
  211. /* -g switch. (Each grid row takes up 4 lines of text.)                      */
  212.  
  213. void ChartGrid()
  214. {
  215.   char sz[cchSzDef];
  216.   int x, y, r, x1, y1, temp;
  217.  
  218. #ifdef INTERPRET
  219.   if (us.fInterpret) {    /* Print interpretation instead if -I in effect. */
  220.     InterpretGrid();
  221.     return;
  222.   }
  223. #endif
  224.  
  225.   for (y1 = 0, y = 1; y <= cObj; y++) if (!ignore[y])
  226.     for (r = 1; r <= 4; r++) {
  227.       for (x1 = 0, x = 1; x <= cObj; x++) if (!ignore[x]) {
  228.         if (y1 > 0 && x1 > 0 && y+r > 2)
  229.           PrintCh((char)(r > 1 ? chV : chC));
  230.         if (r > 1) {
  231.           temp = grid->n[x][y];
  232.  
  233.           /* Print aspect rows. */
  234.  
  235.           if (x < y) {
  236.             if (temp)
  237.               AnsiColor(kAspA[temp]);
  238.             if (r == 2)
  239.               PrintSz(temp ? szAspectAbbrev[temp] : "   ");
  240.             else if (!temp)
  241.               PrintSz("   ");
  242.             else {
  243.               if (r == 3) {
  244.                 if (grid->v[x][y] < 6000)
  245.                   sprintf(sz, "%c%2d", us.fAppSep ?
  246.                     (grid->v[x][y] < 0 ? 'a' : 's') :
  247.                     (grid->v[x][y] < 0 ? '-' : '+'), abs(grid->v[x][y])/60);
  248.                 else
  249.                   sprintf(sz, "%3d", abs(grid->v[x][y])/60);
  250.               } else
  251.                 sprintf(sz, "%02d'", abs(grid->v[x][y])%60);
  252.               PrintSz(sz);
  253.             }
  254.  
  255.           /* Print midpoint rows. */
  256.  
  257.           } else if (x > y) {
  258.             AnsiColor(kSignA(temp));
  259.             if (r == 2) {
  260.               temp = grid->n[x][y];
  261.               sprintf(sz, "%c%c%c", chSig3(temp));
  262.             } else if (r == 3) {
  263.               sprintf(sz, "%2d%c", grid->v[x][y]/60, chDeg0);
  264.             } else
  265.               sprintf(sz, "%02d'", grid->v[x][y]%60);
  266.             PrintSz(sz);
  267.  
  268.           /* Print the diagonal of object names. */
  269.  
  270.           } else {
  271.             AnsiColor(kReverse);
  272.             if (r == 2) {
  273.               AnsiColor(kObjA[y]);
  274.               sprintf(sz, "%c%c%c", chObj3(y));
  275.             } else {
  276.               temp = SFromZ(planet[y]);
  277.               AnsiColor(kSignA(temp));
  278.               if (r == 3)
  279.                 sprintf(sz, "%2d%c", (int)planet[y] - (temp-1)*30, chDeg0);
  280.               else
  281.                 sprintf(sz, "%c%c%c", chSig3(temp));
  282.             }
  283.             PrintSz(sz);
  284.           }
  285.           AnsiColor(kDefault);
  286.         } else
  287.           if (y1 > 0)
  288.             PrintTab(chH, 3);
  289.         x1++;
  290.       }
  291.       if (y+r > 2)
  292.         PrintL();
  293.       y1++;
  294.     }
  295. }
  296.  
  297.  
  298. /* This is a subprocedure of DisplayGrands(). Here we print out one aspect */
  299. /* configuration found by the parent procedure.                            */
  300.  
  301. void PrintGrand(ac, i1, i2, i3, i4)
  302. char ac;
  303. int i1, i2, i3, i4;
  304. {
  305.   char sz[cchSzDef];
  306.   int asp;
  307.  
  308.   switch (ac) {
  309.   case acS : asp = aCon; break;
  310.   case acGT: asp = aTri; break;
  311.   case acTS: asp = aOpp; break;
  312.   case acY : asp = aInc; break;
  313.   case acGC: asp = aSqu; break;
  314.   case acC : asp = aSex; break;
  315.   default: ;
  316.   }
  317.   AnsiColor(kAspA[asp]);
  318.   sprintf(sz, "%-11s", szAspectConfig[ac]); PrintSz(sz);
  319.   AnsiColor(kDefault);
  320.   sprintf(sz, " %s ",
  321.     ac == acS || ac == acGT || ac == acGC ? "with" : "from"); PrintSz(sz);
  322.   AnsiColor(kObjA[i1]);
  323.   sprintf(sz, "%c%c%c: ", chObj3(i1)); PrintSz(sz);
  324.   PrintZodiac(planet[i1]);
  325.   sprintf(sz, " %s ", ac == acS || ac == acGT ? "and" : "to "); PrintSz(sz);
  326.   AnsiColor(kObjA[i2]);
  327.   sprintf(sz, "%c%c%c: ", chObj3(i2)); PrintSz(sz);
  328.   PrintZodiac(planet[i2]);
  329.   sprintf(sz, " %s ", ac == acGC || ac == acC ? "to " : "and"); PrintSz(sz);
  330.   AnsiColor(kObjA[i3]);
  331.   sprintf(sz, "%c%c%c: ", chObj3(i3)); PrintSz(sz);
  332.   PrintZodiac(planet[i3]);
  333.   if (ac == acGC || ac == acC) {
  334.     PrintSz(" to ");
  335.     AnsiColor(kObjA[i4]);
  336.     sprintf(sz, "%c%c%c: ", chObj3(i4)); PrintSz(sz);
  337.     PrintZodiac(planet[i4]);
  338.   }
  339.   PrintL();
  340. }
  341.  
  342.  
  343. /* Scan the aspect grid of a chart and print out any major configurations, */
  344. /* as specified with the -g0 switch.                                       */
  345.  
  346. void DisplayGrands()
  347. {
  348.   int cac = 0, i, j, k, l;
  349.  
  350.   for (i = 1; i <= cObj; i++) if (!ignore[i])
  351.     for (j = 1; j <= cObj; j++) if (j != i && !ignore[j])
  352.       for (k = 1; k <= cObj; k++) if (k != i && k != j && !ignore[k]) {
  353.  
  354.         /* Is there a Stellium among the current three planets? */
  355.  
  356.         if (i < j && j < k && grid->n[i][j] == aCon &&
  357.             grid->n[i][k] == aCon && grid->n[j][k] == aCon) {
  358.           cac++;
  359.           PrintGrand(acS, i, j, k, l);
  360.  
  361.         /* Is there a Grand Trine? */
  362.  
  363.         } else if (i < j && j < k && grid->n[i][j] == aTri &&
  364.             grid->n[i][k] == aTri && grid->n[j][k] == aTri) {
  365.           cac++;
  366.           PrintGrand(acGT, i, j, k, l);
  367.  
  368.         /* Is there a T-Square? */
  369.  
  370.         } else if (j < k && grid->n[j][k] == aOpp &&
  371.             grid->n[Min(i, j)][Max(i, j)] == aSqu &&
  372.             grid->n[Min(i, k)][Max(i, k)] == aSqu) {
  373.           cac++;
  374.           PrintGrand(acTS, i, j, k, l);
  375.  
  376.         /* Is there a Yod? */
  377.  
  378.         } else if (j < k && grid->n[j][k] == aSex &&
  379.             grid->n[Min(i, j)][Max(i, j)] == aInc &&
  380.             grid->n[Min(i, k)][Max(i, k)] == aInc) {
  381.           cac++;
  382.           PrintGrand(acY, i, j, k, l);
  383.         }
  384.         for (l = 1; l <= cObj; l++) if (!ignore[l]) {
  385.  
  386.           /* Is there a Grand Cross among the current four planets? */
  387.  
  388.           if (i < j && i < k && i < l && j < l && grid->n[i][j] == aSqu &&
  389.               grid->n[Min(j, k)][Max(j, k)] == aSqu &&
  390.               grid->n[Min(k, l)][Max(k, l)] == aSqu &&
  391.               grid->n[i][l] == aSqu &&
  392.               MinDistance(planet[i], planet[k]) > 150.0 &&
  393.               MinDistance(planet[j], planet[l]) > 150.0) {
  394.             cac++;
  395.             PrintGrand(acGC, i, j, k, l);
  396.  
  397.           /* Is there a Cradle? */
  398.  
  399.           } else if (i < l && grid->n[Min(i, j)][Max(i, j)] == aSex &&
  400.               grid->n[Min(j, k)][Max(j, k)] == aSex &&
  401.               grid->n[Min(k, l)][Max(k, l)] == aSex &&
  402.               MinDistance(planet[i], planet[l]) > 150.0) {
  403.             cac++;
  404.             PrintGrand(acC, i, j, k, l);
  405.           }
  406.         }
  407.       }
  408.   if (!cac)
  409.     PrintSz("No major configurations in aspect grid.\n");
  410. }
  411.  
  412.  
  413. /* This is subprocedure of ChartWheel(). Here we print out the location */
  414. /* of a particular house cusp as well as what house cusp number it is.  */
  415.  
  416. void PrintHouse(i, left)
  417. int i, left;
  418. {
  419.   char sz[cchSzDef];
  420.  
  421.   if (!left)
  422.     PrintZodiac(house[i]);
  423.   AnsiColor(kSignA(i));
  424.   sprintf(sz, "<%d>", i); PrintSz(sz);
  425.   if (left)
  426.     PrintZodiac(house[i]);
  427.   else
  428.     AnsiColor(kDefault);
  429. }
  430.  
  431.  
  432. /* Another subprocedure of ChartWheel(). Print out one of the chart info */
  433. /* rows in the middle of the wheel (which may be blank) given an index.  */
  434.  
  435. void PrintWheelCenter(irow)
  436. int irow;
  437. {
  438.   char sz[cchSzDef], szT[8];
  439.   int cch, nT;
  440.  
  441.   if (*ciMain.nam == chNull && *ciMain.loc == chNull)    /* Try to center */
  442.     irow--;
  443.   if (*ciMain.nam == chNull && irow >= 1)    /* Don't have blank lines if */
  444.     irow++;                                  /* the name and/or location  */
  445.   if (*ciMain.loc == chNull && irow >= 3)    /* strings are empty.        */
  446.     irow++;
  447.   switch (irow) {
  448.   case 0:
  449.     sprintf(sz, "%s %s chart", szAppName, szVersionCore);
  450.     break;
  451.   case 1:
  452.     sprintf(sz, "%s", ciMain.nam);
  453.     break;
  454.   case 2:
  455.     nT = DayOfWeek(Mon, Day, Yea);
  456.     sprintf(sz, "%c%c%c %s %s", chDay3(nT), SzDate(Mon, Day, Yea, 2),
  457.       SzTim(Tim));
  458.     break;
  459.   case 3:
  460.     sprintf(sz, "%s", ciMain.loc);
  461.     break;
  462.   case 4:
  463.     nT = (int)(RFract(RAbs(Zon))*100.0+rRound);
  464.     sprintf(sz, "%cT %c%02d:%02d, %s", ChDst(Dst),
  465.       Zon > 0.0 ? '-' : '+', (int)RAbs(Zon), nT, SzLocation(Lon, Lat));
  466.     break;
  467.   case 5:
  468.     nT = us.fEuroTime; us.fEuroTime = fTrue;
  469.     sprintf(szT, "%s", SzTim(DegToDec(DFromR(RA)*(24.0/rDegMax))));
  470.     sprintf(sz, "UT: %s, Sid.T: %s", SzTim(Tim+Zon-Dst), szT);
  471.     us.fEuroTime = nT;
  472.     break;
  473.   case 6:
  474.     sprintf(sz, "%s Houses", szSystem[us.nHouseSystem]);
  475.     break;
  476.   case 7:
  477.     sprintf(sz, "%s / %s", us.fSidereal ? "Sidereal" : "Tropical",
  478.       us.objCenter == 0 ? "Heliocentric" :
  479.       (us.objCenter == 1 ? "Geocentric" : szObjName[us.objCenter]));
  480.     break;
  481.   case 8:
  482.     sprintf(sz, "Julian Day = %12.4f", JulianDayFromTime(T));
  483.     break;
  484.   default:
  485.     *sz = chNull;
  486.   }
  487.   cch = CchSz(sz);
  488.   nT = WHEELCOLS*2-1 + is.fSeconds*8;
  489.   PrintTab(' ', (nT - cch) / 2);
  490.   PrintSz(sz);
  491.   PrintTab(' ', nT-cch - (nT - cch) / 2);
  492. }
  493.  
  494.  
  495. /* Yet another subprocedure of ChartWheel(). Here we print out one line */
  496. /* in a particular house cell (which may be blank).                     */
  497.  
  498. void PrintWheelSlot(obj)
  499. int obj;
  500. {
  501.   char sz[cchSzDef];
  502.  
  503.   if (obj) {
  504.     AnsiColor(kObjA[obj]);
  505.     sprintf(sz, " %c%c%c ", chObj3(obj)); PrintSz(sz);
  506.     PrintZodiac(planet[obj]);
  507.     sprintf(sz, "%c ", ret[obj] < 0.0 ? 'r' : ' '); PrintSz(sz);
  508.     PrintTab(' ', WHEELCOLS-15);
  509.   } else                            /* This particular line is blank. */
  510.     PrintTab(' ', WHEELCOLS-1 + is.fSeconds*4);
  511. }
  512.  
  513.  
  514. /* Display all the objects in a wheel format on the screen, as specified */
  515. /* with the -w switch. The wheel is divided into the 12 houses and the   */
  516. /* planets are placed accordingly.                                       */
  517.  
  518. void ChartWheel()
  519. {
  520.   byte wheel[cSign][WHEELROWS];
  521.   int wheelcols, count = 0, i, j, k, l;
  522.  
  523.   /* If the seconds (-b0) flag is set, we'll print all planet and house    */
  524.   /* locations to the nearest zodiac second instead of just to the minute. */
  525.  
  526.   wheelcols = WHEELCOLS + is.fSeconds*4;
  527.  
  528.   for (i = 0; i < cSign; i++)
  529.     for (j = 0; j < us.nWheelRows; j++)    /* Clear out array from the */
  530.       wheel[i][j] = 0;                     /* last time we used it.    */
  531.  
  532.   /* This section of code places each object in the wheel house array. */
  533.  
  534.   for (i = 1; i <= cObj && count < us.nWheelRows*12; i++) {
  535.     if (ignore[i] || (FCusp(i) &&
  536.       MinDistance(planet[i], house[i-oAsc+1]) < rRound/60.0))
  537.       continue;
  538.  
  539.     /* Try to put object in its proper house. If no room, */
  540.     /* then overflow over to the next succeeding house.   */
  541.  
  542.     for (j = inhouse[i]-1; j < cSign; j = j < cSign ? (j+1)%cSign : j) {
  543.  
  544.       /* Now try to find the proper place in the house to put the object. */
  545.       /* This is in sorted order, although a check is made for 0 Aries.   */
  546.  
  547.       if (wheel[j][us.nWheelRows-1] > 0)
  548.         continue;
  549.       l = house[j+1] > house[Mod12(j+2)];
  550.       for (k = 0; wheel[j][k] > 0 && (planet[i] >= planet[wheel[j][k]] ||
  551.          (l && planet[i] < rDegHalf && planet[wheel[j][k]] > rDegHalf)) &&
  552.         !(l && planet[i] > rDegHalf && planet[wheel[j][k]] < rDegHalf); k++)
  553.         ;
  554.  
  555.       /* Actually insert object in proper place. */
  556.  
  557.       if (wheel[j][k] <= 0)
  558.         wheel[j][k] = i;
  559.       else {
  560.         for (l = us.nWheelRows-1; l > k; l--)
  561.           wheel[j][l] = wheel[j][l-1];
  562.         wheel[j][k] = i;
  563.       }
  564.       count++;
  565.       j = cSign;
  566.     }
  567.   }
  568.  
  569.   /* Now, if this is really the -w switch and not -w0, then reverse the */
  570.   /* order of objects in western houses for more intuitive reading.     */
  571.  
  572.   if (!us.fWheelReverse)
  573.     for (i = 3; i < 9; i++)
  574.       for (j = 0; j < us.nWheelRows/2; j++) {
  575.         k = us.nWheelRows-1-j;
  576.         l = wheel[i][j]; wheel[i][j] = wheel[i][k]; wheel[i][k] = l;
  577.       }
  578.  
  579.   /* Here we actually print the wheel and the objects in it. */
  580.  
  581.   PrintCh(chNW); PrintTab(chH, WHEELCOLS-8); PrintHouse(11, fTrue);
  582.   PrintTab(chH, WHEELCOLS-11); PrintHouse(10, fTrue);
  583.   PrintTab(chH, WHEELCOLS-10); PrintHouse(9, fTrue);
  584.   PrintTab(chH, wheelcols-4); PrintCh(chNE); PrintL();
  585.   for (i = 0; i < us.nWheelRows; i++) {
  586.     for (j = 10; j >= 7; j--) {
  587.       PrintCh(chV); PrintWheelSlot(wheel[j][i]);
  588.     }
  589.     PrintCh(chV); PrintL();
  590.   }
  591.   PrintHouse(12, fTrue); PrintTab(chH, WHEELCOLS-11);
  592.   PrintCh(chC); PrintTab(chH, wheelcols-1); PrintCh(chJN);
  593.   PrintTab(chH, wheelcols-1); PrintCh(chC); PrintTab(chH, WHEELCOLS-10);
  594.   PrintHouse(8, fFalse); PrintL();
  595.   for (i = 0; i < us.nWheelRows; i++) {
  596.     PrintCh(chV); PrintWheelSlot(wheel[11][i]); PrintCh(chV);
  597.     PrintWheelCenter(i);
  598.     PrintCh(chV); PrintWheelSlot(wheel[6][i]);
  599.     PrintCh(chV); PrintL();
  600.   }
  601.   PrintHouse(1, fTrue); PrintTab(chH, WHEELCOLS-10);
  602.   PrintCh(chJW); PrintWheelCenter(us.nWheelRows); PrintCh(chJE);
  603.   PrintTab(chH, WHEELCOLS-10); PrintHouse(7, fFalse); PrintL();
  604.   for (i = 0; i < us.nWheelRows; i++) {
  605.     PrintCh(chV); PrintWheelSlot(wheel[0][i]); PrintCh(chV);
  606.     PrintWheelCenter(us.nWheelRows+1 + i);
  607.     PrintCh(chV); PrintWheelSlot(wheel[5][i]);
  608.     PrintCh(chV); PrintL();
  609.   }
  610.   PrintHouse(2, fTrue); PrintTab(chH, WHEELCOLS-10);
  611.   PrintCh(chC); PrintTab(chH, wheelcols-1); PrintCh(chJS);
  612.   PrintTab(chH, wheelcols-1); PrintCh(chC);
  613.   PrintTab(chH, WHEELCOLS-10); PrintHouse(6, fFalse); PrintL();
  614.   for (i = 0; i < us.nWheelRows; i++) {
  615.     for (j = 1; j <= 4; j++) {
  616.       PrintCh(chV); PrintWheelSlot(wheel[j][i]);
  617.     }
  618.     PrintCh(chV); PrintL();
  619.   }
  620.   PrintCh(chSW); PrintTab(chH, wheelcols-4); PrintHouse(3, fFalse);
  621.   PrintTab(chH, WHEELCOLS-10); PrintHouse(4, fFalse);
  622.   PrintTab(chH, WHEELCOLS-10); PrintHouse(5, fFalse);
  623.   PrintTab(chH, WHEELCOLS-7); PrintCh(chSE); PrintL();
  624. }
  625.  
  626.  
  627. /* Display all aspects between objects in the chart, one per line, in       */
  628. /* sorted order based on the total "power" of the aspect, as specified with */
  629. /* the -a switch. The same influences used for -I charts are used here.     */
  630.  
  631. void ChartAspect()
  632. {
  633.   int ca[cAspect + 1], co[objMax];
  634.   char sz[cchSzDef];
  635.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  636.   real ip, jp, rPowSum = 0.0;
  637.  
  638.   ClearB((lpbyte)ca, (cAspect + 1)*(int)sizeof(int));
  639.   ClearB((lpbyte)co, objMax*(int)sizeof(int));
  640.   loop {
  641.     phi = -1;
  642.  
  643.     /* Search for the next most powerful aspect in the aspect grid. */
  644.  
  645.     for (i = 2; i <= cObj; i++) if (!ignore[i])
  646.       for (j = 1; j < i; j++) if (!ignore[j])
  647.         if (k = grid->n[j][i]) {
  648.           ip = i <= oNorm ? rObjInf[i] : 2.5;
  649.           jp = j <= oNorm ? rObjInf[j] : 2.5;
  650.           p = (int)(rAspInf[k]*(ip+jp)/2.0*
  651.             (1.0-RAbs((real)(grid->v[j][i]))/60.0/rAspOrb[k])*1000.0);
  652.           if ((p < pcut || (p == pcut && (i > icut ||
  653.             (i == icut && j > jcut)))) && p > phi) {
  654.             ihi = i; jhi = j; phi = p; ahi = k;
  655.           }
  656.         }
  657.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  658.       break;
  659.     pcut = phi; icut = ihi; jcut = jhi;
  660.     count++;                               /* Display the current aspect.   */
  661. #ifdef INTERPRET
  662.     if (us.fInterpret) {                   /* Interpret it if -I in effect. */
  663.       InterpretAspect(jhi, ihi);
  664.       continue;
  665.     }
  666. #endif
  667.     rPowSum += (real)phi/1000.0;
  668.     ca[ahi]++;
  669.     co[jhi]++; co[ihi]++;
  670.     sprintf(sz, "%3d: ", count); PrintSz(sz);
  671.     PrintAspect(jhi, SFromZ(planet[jhi]), (int)RSgn(ret[jhi]), ahi,
  672.       ihi, SFromZ(planet[ihi]), (int)RSgn(ret[ihi]), 'a');
  673.     k = grid->v[jhi][ihi];
  674.     AnsiColor(k < 0 ? kWhite : kLtGray);
  675.     sprintf(sz, " - orb: %c%d%c%02d'",
  676.       us.fAppSep ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  677.       abs(k)/60, chDeg1, abs(k)%60); PrintSz(sz);
  678.     AnsiColor(kDkGreen);
  679.     sprintf(sz, " - power:%6.2f\n", (real)phi/1000.0); PrintSz(sz);
  680.     AnsiColor(kDefault);
  681.   }
  682.  
  683.   /* Now, if the -a0 switch is set, display summary information, the total */
  684.   /* number of aspects of each type, and the # of aspects to each object.  */
  685.  
  686.   if (!us.fAspSummary)
  687.     return;
  688.   PrintL();
  689.   AnsiColor(kDkGreen);
  690.   sprintf(sz, "Sum power:%7.2f - Average power:%6.2f\n",
  691.     rPowSum, rPowSum/(real)count); PrintSz(sz);
  692.   k = us.fParallel ? Min(us.nAsp, aOpp) : us.nAsp;
  693.   for (j = 0, i = 1; i <= k; i++) if (!ignorea(i)) {
  694.     if (!(j & 7)) {
  695.       if (j)
  696.         PrintL();
  697.     } else
  698.       PrintSz("   ");
  699.     AnsiColor(kAspA[i]);
  700.     sprintf(sz, "%s:%3d", szAspectAbbrev[i], ca[i]); PrintSz(sz);
  701.     j++;
  702.   }
  703.   PrintL();
  704.   for (j = 0, i = 1; i <= cObj; i++) if (!ignore[i]) {
  705.     if (!(j & 7)) {
  706.       if (j)
  707.         PrintL();
  708.     } else
  709.       PrintSz("   ");
  710.     AnsiColor(kObjA[i]);
  711.     sprintf(sz, "%c%c%c:%3d", chObj3(i), co[i]); PrintSz(sz);
  712.     j++;
  713.   }
  714.   PrintL();
  715. }
  716.  
  717.  
  718. /* Display locations of all midpoints between objects in the chart, */
  719. /* one per line, in sorted zodiac order from zero Aries onward, as  */
  720. /* specified with the -m switch.                                    */
  721.  
  722. void ChartMidpoint()
  723. {
  724.   int cs[cSign + 1];
  725.   char sz[cchSzDef];
  726.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, k, count = 0;
  727.   long lSpanSum = 0;
  728.   real l, n, mid;
  729.  
  730.   ClearB((lpbyte)cs, (cSign + 1)*(int)sizeof(int));
  731.   is.fSeconds = fFalse;
  732.   loop {
  733.     mlo = 21600;
  734.  
  735.     /* Search for the next closest midpoint farther down in the zodiac. */
  736.  
  737.     for (i = 1; i < cObj; i++) if (!ignore[i])
  738.       for (j = i+1; j <= cObj; j++) if (!ignore[j]) {
  739.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  740.         if ((m > mcut || (m == mcut && (i > icut ||
  741.           (i == icut && j > jcut)))) && m < mlo) {
  742.           ilo = i; jlo = j; mlo = m;
  743.         }
  744.       }
  745.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  746.       break;
  747.     mcut = mlo; icut = ilo; jcut = jlo;
  748.     count++;                               /* Display the current midpoint. */
  749. #ifdef INTERPRET
  750.     if (us.fInterpret) {                   /* Interpret it if -I in effect. */
  751.       InterpretMidpoint(ilo, jlo);
  752.       continue;
  753.     }
  754. #endif
  755.     cs[mlo/60/30+1]++;
  756.     sprintf(sz, "%4d: ", count); PrintSz(sz);
  757.     mid = (real)mlo/60.0; PrintZodiac(mid);
  758.     PrintCh(' ');
  759.     PrintAspect(ilo, SFromZ(planet[ilo]), (int)RSgn(ret[ilo]), 0,
  760.       jlo, SFromZ(planet[jlo]), (int)RSgn(ret[jlo]), 'm');
  761.     AnsiColor(kDefault);
  762.     m = (int)(MinDistance(planet[ilo], planet[jlo])*60.0);
  763.     lSpanSum += m;
  764.     sprintf(sz, "-%4d%c%02d' degree span.\n", m/60, chDeg1, m%60);
  765.     PrintSz(sz);
  766.  
  767.     /* If the -ma switch is set, determine and display each aspect from one */
  768.     /* of the planets to the current midpoint, and the aspect's orb.        */
  769.  
  770.     if (!us.fMidAspect)
  771.       continue;
  772.     for (i = 1; i < cObj; i++) if (!ignore[i]) {
  773.       l = MinDistance(planet[i], mid);
  774.       for (k = us.nAsp; k >= 1; k--) {
  775.         if (!FAcceptAspect(i, k, ilo))
  776.           continue;
  777.         n = l-rAspAngle[k];
  778.         if (RAbs(n) < GetOrb(i, ilo, k)) {
  779.           if (us.fAppSep)
  780.             n = RSgn2((ret[ilo]+ret[jlo])/2.0-ret[i])*
  781.               RSgn2(MinDifference(planet[i], mid))*RSgn2(n)*RAbs(n);
  782.           PrintSz("      Midpoint "); PrintZodiac(mid); PrintSz(" makes ");
  783.           AnsiColor(kAspA[k]); PrintSz(szAspectAbbrev[k]);
  784.           AnsiColor(kDefault); PrintSz(" to ");
  785.           AnsiColor(kObjA[i]); sprintf(sz, "%.10s", szObjName[i]);
  786.           PrintSz(sz);
  787.           PrintTab(' ', 10-CchSz(szObjName[i]));
  788.           j = (int)(n*60.0);
  789.           AnsiColor(j < 0.0 ? kWhite : kLtGray);
  790.           sprintf(sz, "- orb: %c%d%c%02d'",
  791.             us.fAppSep ? (j < 0 ? 'a' : 's') : (j < 0 ? '-' : '+'),
  792.             abs(j)/60, chDeg1, abs(j)%60); PrintSz(sz);
  793.           PrintL();
  794.           AnsiColor(kDefault);
  795.         }
  796.       }
  797.     }
  798.   }
  799.   is.fSeconds = us.fSeconds;
  800.  
  801.   /* Now, if the -m0 switch is set, display summary information as well, */
  802.   /* including the total number of midpoints in each sign.               */
  803.  
  804.   if (!us.fMidSummary)
  805.     return;
  806.   PrintL();
  807.   m = (int)(lSpanSum/count);
  808.   sprintf(sz, "Average span:%4d%c%02d'\n", m/60, chDeg1, m%60); PrintSz(sz);
  809.   for (i = 1; i <= cSign; i++) {
  810.     if (i == sLib)
  811.       PrintL();
  812.     else if (i != sAri)
  813.       PrintSz("   ");
  814.     AnsiColor(kSignA(i));
  815.     sprintf(sz, "%c%c%c:%3d", chSig3(i), cs[i]); PrintSz(sz);
  816.   }
  817.   PrintL();
  818. }
  819.  
  820.  
  821. /* Display locations of the objects on the screen with respect to the local */
  822. /* horizon, as specified with the -Z switch.                                */
  823.  
  824. void ChartHorizon()
  825. {
  826.   char sz[cchSzDef], szFormat[cchSzDef];
  827.   real lon, lat, sx, sy, vx, vy,
  828.     lonz[objMax], latz[objMax], azi[objMax], alt[objMax];
  829.   int fPrime, i, j, k, tot;
  830.  
  831.   /* Set up some initial variables. */
  832.  
  833.   fPrime = us.fPrimeVert;
  834.   lon = RFromD(Mod(Lon)); lat = RFromD(Lat);
  835.   tot = us.nStar ? cObj : oNorm;
  836.  
  837.   /* First find zenith location on Earth of each object. */
  838.  
  839.   for (i = 1; i <= tot; i++) if (!ignore[i] || i == oMC) {
  840.     lonz[i] = RFromD(Tropical(planet[i])); latz[i] = RFromD(planetalt[i]);
  841.     EclToEqu(&lonz[i], &latz[i]);
  842.   }
  843.  
  844.   /* Then, convert this to local horizon altitude and azimuth. */
  845.  
  846.   for (i = 1; i <= tot; i++) if (!ignore[i] && i != oMC) {
  847.     lonz[i] = RFromD(Mod(DFromR(lonz[oMC]-lonz[i]+lon)));
  848.     lonz[i] = RFromD(Mod(DFromR(lonz[i]-lon+rPiHalf)));
  849.     EquToLocal(&lonz[i], &latz[i], rPiHalf-lat);
  850.     azi[i] = rDegMax-DFromR(lonz[i]); alt[i] = DFromR(latz[i]);
  851.   }
  852.  
  853.   /* If the -Z0 switch flag is in effect, convert from altitude/azimuth  */
  854.   /* coordinates to prime vertical coordinates that we'll print instead. */
  855.  
  856.   if (fPrime) {
  857.     for (i = 1; i <= tot; i++) if (!ignore[i]) {
  858.       azi[i] = RFromD(azi[i]); alt[i] = RFromD(alt[i]);
  859.       CoorXform(&azi[i], &alt[i], rPiHalf);
  860.       azi[i] = DFromR(azi[i]); alt[i] = DFromR(alt[i]);
  861.     }
  862.   }
  863.  
  864.   /* Now, actually print the location of each object. */
  865.  
  866.   sprintf(szFormat, is.fSeconds ? " " : "");
  867.   sprintf(sz, "Body %s%sAltitude%s %s%sAzimuth%s%s  Azi. Vector%s    ",
  868.     szFormat, szFormat, szFormat, szFormat, szFormat, szFormat, szFormat,
  869.     szFormat); PrintSz(sz);
  870.   sprintf(sz, "%s Vector%s%s    Moon Vector\n\n",
  871.     us.objCenter ? "Sun" : "Earth", szFormat, szFormat); PrintSz(sz);
  872.   for (k = 1; k <= tot; k++) {
  873.     i = k <= oNorm ? k : oNorm+starname[k-oNorm];
  874.     if (ignore[i] || !FThing(i))
  875.       continue;
  876.     AnsiColor(kObjA[i]);
  877.     sprintf(sz, "%-4.4s: ", szObjName[i]); PrintSz(sz);
  878.     PrintAltitude(alt[i]);
  879.  
  880.     /* Determine directional vector based on azimuth. */
  881.  
  882.     sprintf(sz, " %s", SzDegree(azi[i])); PrintSz(sz);
  883.     sx = RCos(RFromD(azi[i])); sy = RSin(RFromD(azi[i]));
  884.     if (RAbs(sx) < RAbs(sy)) {
  885.       vx = RAbs(sx / sy); vy = 1.0;
  886.     } else {
  887.       vy = RAbs(sy / sx); vx = 1.0;
  888.     }
  889.     sprintf(sz, is.fSeconds ? " (%.3f%c" : " (%.2f%c", vy,
  890.       sy < 0.0 ? (fPrime ? 'u' : 's') : (fPrime ? 'd' : 'n')); PrintSz(sz);
  891.     sprintf(sz, is.fSeconds ? " %.2f%c)" : " %.2f%c)", vx,
  892.       sx > 0.0 ? 'e' : 'w'); PrintSz(sz);
  893.  
  894.     /* Determine distance vector of current object from Sun and Moon. */
  895.  
  896.     vx = azi[1]-azi[i]; vy = azi[2]-azi[i];
  897.     j = 1 + is.fSeconds;
  898.     sprintf(szFormat, " [%%%d.%df%%%d.%df] [%%%d.%df%%%d.%df]",
  899.       j+5, j, j+5, j, j+5, j, j+5, j);
  900.     sprintf(sz, szFormat,
  901.       RAbs(vx) < rDegHalf ? vx : RSgn(vx)*(rDegMax-RAbs(vx)), alt[1]-alt[i],
  902.       RAbs(vy) < rDegHalf ? vy : RSgn(vy)*(rDegMax-RAbs(vy)), alt[2]-alt[i]);
  903.     PrintSz(sz);
  904.     if (!is.fSeconds && i >= uranLo) {
  905.       if (i <= uranHi)
  906.         sprintf(sz, "  Uranian #%d", i-uranLo+1);
  907.       else
  908.         sprintf(sz, "  Star #%2d", i-starLo+1);
  909.       PrintSz(sz);
  910.     }
  911.     PrintL();
  912.   }
  913.   AnsiColor(kDefault);
  914. }
  915.  
  916.  
  917. /* Display x,y,z locations of each body (in AU) with respect to the Sun */
  918. /* (or whatever the specified center planet is), as in the -S switch.   */
  919. /* These values were already determined when calculating the planet     */
  920. /* positions themselves, so this procedure is basically just a loop.    */
  921.  
  922. void ChartOrbit()
  923. {
  924.   char sz[cchSzDef], szFormat[cchSzDef];
  925.   real x, y, z;
  926.   int i;
  927.  
  928.   sprintf(szFormat, is.fSeconds ? " " : "");
  929.   sprintf(sz, "Body%s    Angle%s%s%s%s    ",
  930.     szFormat, szFormat, szFormat, szFormat, szFormat);
  931.   PrintSz(sz);
  932.   sprintf(sz,
  933.     "%sX axis%s%s%s    %sY axis%s%s%s    %sZ axis%s%s%s    %sLength\n",
  934.     szFormat, szFormat, szFormat, szFormat, szFormat, szFormat, szFormat,
  935.     szFormat, szFormat, szFormat, szFormat, szFormat, szFormat);
  936.   PrintSz(sz);
  937.   for (i = 0; i <= oNorm; i++) {
  938.     if (ignore[i] || (!FThing(i) ||
  939.       ((i == oMoo || i == oNod || i == oSou) && !us.fPlacalc)))
  940.       continue;
  941.     AnsiColor(kObjA[i]);
  942.     sprintf(sz, "%c%c%c%c: ", chObj3(i),
  943.       szObjName[i][3] ? szObjName[i][3] : ' '); PrintSz(sz);
  944.     x = spacex[i]; y = spacey[i]; z = spacez[i];
  945.     sprintf(sz, is.fSeconds ? "[%11.7f] [%11.7f] [%11.7f] [%11.7f] [%11.7f]" :
  946.       "[%7.3f] [%7.3f] [%7.3f] [%7.3f] [%7.3f]",
  947.       planet[i], x, y, z, RSqr(x*x+y*y+z*z)); PrintSz(sz);
  948.     if (!is.fSeconds && i >= uranLo) {
  949.       sprintf(sz, "  Uranian #%d", i-uranLo+1); PrintSz(sz);
  950.     }
  951.     PrintL();
  952.   }
  953.   AnsiColor(kDefault);
  954. }
  955.  
  956.  
  957. /* Print the locations of the astro-graph lines on the Earth as specified */
  958. /* with the -L switch. This includes Midheaven and Nadir lines, zenith    */
  959. /* positions, and locations of Ascendant and Descendant lines.            */
  960.  
  961. void ChartAstroGraph()
  962. {
  963.   CrossInfo FPTR *c;
  964.   char sz[cchSzDef];
  965.   real planet1[objMax], planet2[objMax], mc[objMax], ic[objMax],
  966.     as[objMax], ds[objMax], as1[objMax], ds1[objMax],
  967.     lo = Lon, longm, w, x, y, z, ad, oa, am, od, dm;
  968.   int cCross = 0, tot = cObj, i, j, k, l, m, n;
  969.  
  970.   if (us.fLatitudeCross)
  971.     {
  972.     if ((c = (CrossInfo FPTR *)
  973.       PAllocate(sizeof(CrossInfo), fFalse, "crossing table")) == NULL)
  974.       return;
  975.     }
  976.  
  977. #ifdef MATRIX
  978.   for (i = 1; i <= cObj; i++) if (!ignore[i] || i == oMC) {
  979.     planet1[i] = RFromD(Tropical(i == oMC ? MC : planet[i]));
  980.     planet2[i] = RFromD(planetalt[i]);     /* Calculate zenith location on */
  981.     EclToEqu(&planet1[i], &planet2[i]);    /* Earth of each object.        */
  982.   }
  983.  
  984.   /* Print header. */
  985.  
  986.   PrintSz("Object :");
  987.   for (j = 0, i = 1; i <= cObj; i++)
  988.     if (!ignore[i] && FThing(i)) {
  989.       AnsiColor(kObjA[i]);
  990.       sprintf(sz, " %c%c%c", chObj3(i)); PrintSz(sz);
  991.       j++;
  992.     }
  993.   AnsiColor(kDefault);
  994.   PrintSz("\n------ :");
  995.   for (i = 1; i <= tot; i++)
  996.     if (!ignore[i] && FThing(i))
  997.       PrintSz(" ###");
  998.  
  999.   /* Print the longitude locations of the Midheaven lines. */
  1000.  
  1001.   PrintSz("\nMidheav: ");
  1002.   if (lo < 0.0)
  1003.     lo += rDegMax;
  1004.   for (i = 1; i <= tot; i++)
  1005.     if (!ignore[i] && FThing(i)) {
  1006.     AnsiColor(kObjA[i]);
  1007.     x = planet1[oMC]-planet1[i];
  1008.     if (x < 0.0)
  1009.       x += 2.0*rPi;
  1010.     if (x > rPi)
  1011.       x -= 2.0*rPi;
  1012.     z = lo+DFromR(x);
  1013.     if (z > rDegHalf)
  1014.       z -= rDegMax;
  1015.     mc[i] = z;
  1016.     sprintf(sz, "%3.0f%c", RAbs(z), z < 0.0 ? 'e' : 'w'); PrintSz(sz);
  1017.   }
  1018.   AnsiColor(kDefault);
  1019.  
  1020.   /* The Nadir lines are just always 180 degrees away from the Midheaven. */
  1021.  
  1022.   PrintSz("\nNadir  : ");
  1023.   for (i = 1; i <= tot; i++)
  1024.     if (!ignore[i] && FThing(i)) {
  1025.     AnsiColor(kObjA[i]);
  1026.     z = mc[i] + rDegHalf;
  1027.     if (z > rDegHalf)
  1028.       z -= rDegMax;
  1029.     ic[i] = z;
  1030.     sprintf(sz, "%3.0f%c", RAbs(z), z < 0.0 ? 'e' : 'w'); PrintSz(sz);
  1031.   }
  1032.   AnsiColor(kDefault);
  1033.  
  1034.   /* Print the Zenith latitude locations. */
  1035.  
  1036.   PrintSz("\nZenith : ");
  1037.   for (i = 1; i <= tot; i++)
  1038.     if (!ignore[i] && FThing(i)) {
  1039.       AnsiColor(kObjA[i]);
  1040.       y = DFromR(planet2[i]);
  1041.       sprintf(sz, "%3.0f%c", RAbs(y), y < 0.0 ? 's' : 'n'); PrintSz(sz);
  1042.       as[i] = ds[i] = as1[i] = ds1[i] = rLarge;
  1043.     }
  1044.   PrintL2();
  1045.  
  1046.   /* Now print the locations of Ascendant and Descendant lines. Since these */
  1047.   /* are curvy, we loop through the latitudes, and for each object at each  */
  1048.   /* latitude, print the longitude location of the line in question.        */
  1049.  
  1050.   longm = RFromD(Mod(DFromR(planet1[oMC])+lo));
  1051.   for (j = 80; j >= -80; j -= us.nAstroGraphStep) {
  1052.     AnsiColor(kDefault);
  1053.     sprintf(sz, "Asc@%2d%c: ", j >= 0 ? j : -j, j < 0 ? 's' : 'n');
  1054.     PrintSz(sz);
  1055.     for (i = 1; i <= tot; i++)
  1056.       if (!ignore[i] && FThing(i)) {
  1057.       AnsiColor(kObjA[i]);
  1058.       ad = RTan(planet2[i])*RTan(RFromD(j));
  1059.       if (ad*ad > 1.0) {
  1060.         PrintSz(" -- ");
  1061.         as1[i] = ds1[i] = cp2.dir[i] = rLarge;
  1062.       } else {
  1063.         ad = RAsin(ad);
  1064.         oa = planet1[i]-ad;
  1065.         if (oa < 0.0)
  1066.           oa += 2.0*rPi;
  1067.         am = oa-rPiHalf;
  1068.         if (am < 0.0)
  1069.           am += 2.0*rPi;
  1070.         z = longm-am;
  1071.         if (z < 0.0)
  1072.           z += 2.0*rPi;
  1073.         if (z > rPi)
  1074.           z -= 2.0*rPi;
  1075.         as1[i] = as[i];
  1076.         as[i] = z = DFromR(z);
  1077.         cp2.dir[i] = ad;
  1078.         sprintf(sz, "%3.0f%c", RAbs(z), z < 0.0 ? 'e' : 'w'); PrintSz(sz);
  1079.       }
  1080.     }
  1081.  
  1082.     /* Again, the Descendant position is related to the Ascendant's,  */
  1083.     /* being a mirror image, so it can be calculated somewhat easier. */
  1084.  
  1085.     AnsiColor(kDefault);
  1086.     sprintf(sz, "\nDsc@%2d%c: ", j >= 0 ? j : -j, j < 0 ? 's' : 'n');
  1087.     PrintSz(sz);
  1088.     for (i = 1; i <= tot; i++)
  1089.       if (!ignore[i] && FThing(i)) {
  1090.       AnsiColor(kObjA[i]);
  1091.       ad = cp2.dir[i];
  1092.       if (ad == rLarge)
  1093.         PrintSz(" -- ");
  1094.       else {
  1095.         od = planet1[i]+ad;
  1096.         dm = od+rPiHalf;
  1097.         z = longm-dm;
  1098.         if (z < 0.0)
  1099.           z += 2.0*rPi;
  1100.         if (z > rPi)
  1101.           z -= 2.0*rPi;
  1102.         ds1[i] = ds[i];
  1103.         ds[i] = z = DFromR(z);
  1104.         sprintf(sz, "%3.0f%c", RAbs(z), z < 0.0 ? 'e' : 'w'); PrintSz(sz);
  1105.       }
  1106.     }
  1107.     PrintL();
  1108. #endif /* MATRIX */
  1109.  
  1110.     /* Now, if the -L0 switch is in effect, then take these line positions, */
  1111.     /* which we saved in an array above as we were printing them, and       */
  1112.     /* calculate and print the latitude crossings.                          */
  1113.  
  1114.     if (us.fLatitudeCross)
  1115.       for (l = 1; l <= cObj; l++) if (!ignore[l] && FThing(l))
  1116.         for (k = 1; k <= cObj; k++) {
  1117.           if (ignore[k] || !FThing(k))
  1118.             continue;
  1119.           for (n = 0; n <= 1; n++) {
  1120.             x = n ? ds1[l] : as1[l];
  1121.             y = n ? ds[l] : as[l];
  1122.             for (m = 0; m <= 1; m++) {
  1123.  
  1124.             /* Check if Ascendant/Descendant cross Midheaven/Nadir. */
  1125.  
  1126.             z = m ? ic[k] : mc[k];
  1127.             if (cCross < MAXCROSS &&
  1128.               RAbs(x-y) < rDegHalf && RSgn(z-x) != RSgn(z-y)) {
  1129.               c->obj1[cCross] = n ? -l : l;
  1130.               c->obj2[cCross] = m ? -k : k;
  1131.               c->lat[cCross] = (real)j+5.0*RAbs(z-y)/RAbs(x-y);
  1132.               c->lon[cCross] = z;
  1133.               cCross++;
  1134.             }
  1135.  
  1136.             /* Check if Ascendant/Descendant cross another Asc/Des. */
  1137.  
  1138.             w = m ? ds1[k] : as1[k];
  1139.             z = m ? ds[k] : as[k];
  1140.             if (cCross < MAXCROSS && k > l &&
  1141.                 RAbs(x-y)+RAbs(w-z) < rDegHalf && RSgn(w-x) != RSgn(z-y)) {
  1142.               c->obj1[cCross] = n ? -l : l;
  1143.               c->obj2[cCross] = 100+(m ? -k : k);
  1144.               c->lat[cCross] = (real)j+5.0*
  1145.                 RAbs(y-z)/(RAbs(x-w)+RAbs(y-z));
  1146.               c->lon[cCross] = Min(x, y)+RAbs(x-y)*
  1147.                 RAbs(y-z)/(RAbs(x-w)+RAbs(y-z));
  1148.               cCross++;
  1149.             }
  1150.           }
  1151.         }
  1152.     }
  1153.   }
  1154.   if (!us.fLatitudeCross)
  1155.     return;
  1156.   PrintL();
  1157.  
  1158.   /* Now, print out all the latitude crossings we found.  */
  1159.   /* First, we sort them in order of decreasing latitude. */
  1160.  
  1161.   for (i = 1; i < cCross; i++) {
  1162.     j = i-1;
  1163.     while (j >= 0 && c->lat[j] < c->lat[j+1]) {
  1164.       SwapN(c->obj1[j], c->obj1[j+1]); SwapN(c->obj2[j], c->obj2[j+1]);
  1165.       SwapR(&c->lat[j], &c->lat[j+1]); SwapR(&c->lon[j], &c->lon[j+1]);
  1166.       j--;
  1167.     }
  1168.   }
  1169.   for (i = 1; i < cCross; i++) {
  1170.     j = abs(c->obj1[i]);
  1171.     AnsiColor(kObjA[j]);
  1172.     sprintf(sz, "%c%c%c ", chObj3(j)); PrintSz(sz);
  1173.     AnsiColor(kElemA[c->obj1[i] > 0 ? eFir : eAir]);
  1174.     PrintSz(c->obj1[i] > 0 ? "Ascendant " : "Descendant");
  1175.     AnsiColor(kWhite);
  1176.     PrintSz(" crosses ");
  1177.     j = abs(c->obj2[i] - (c->obj2[i] < 50 ? 0 : 100));
  1178.     AnsiColor(kObjA[j]);
  1179.     sprintf(sz, "%c%c%c ", chObj3(j)); PrintSz(sz);
  1180.     AnsiColor(kElemA[c->obj2[i] < 50 ?
  1181.       (c->obj2[i] > 0 ? eEar : eWat) : (c->obj2[i] > 100 ? eFir : eAir)]);
  1182.     sprintf(sz, "%s ", c->obj2[i] < 50 ? (c->obj2[i] > 0 ? "Midheaven " :
  1183.       "Nadir     ") : (c->obj2[i] > 100 ? "Ascendant " : "Descendant"));
  1184.     PrintSz(sz);
  1185.     AnsiColor(kDefault);
  1186.     sprintf(sz, "at %s%c,", SzDegree(c->lon[i]),
  1187.       c->lon[i] < 0.0 ? 'E' : 'W'); PrintSz(sz);
  1188.     j = (int)(RFract(RAbs(c->lat[i]))*60.0);
  1189.     sprintf(sz, "%s%c\n", SzDegree(c->lat[i]),
  1190.       c->lat[i] < 0.0 ? 'S' : 'N'); PrintSz(sz);
  1191.   }
  1192.   DeallocateFar(c);
  1193.   if (!cCross) {
  1194.     AnsiColor(kDefault);
  1195.     PrintSz("No latitude crossings.\n");
  1196.   }
  1197. }
  1198.  
  1199.  
  1200. /* Another important procedure: Display any of the types of (text) charts    */
  1201. /* that the user specified they wanted, by calling the appropriate routines. */
  1202.  
  1203. void PrintChart(fProg)
  1204. bool fProg;
  1205. {
  1206.   int fCall = fFalse;
  1207.  
  1208.   if (us.fListing) {
  1209.     if (is.fMult)
  1210.       PrintL2();
  1211.     if (us.nRel < rcDifference)
  1212.       ChartListing();
  1213.     else
  1214.  
  1215.       /* If the -rb or -rd relationship charts are in effect, then instead  */
  1216.       /* of doing the standard -v chart, print either of these chart types. */
  1217.  
  1218.       DisplayRelation();
  1219.     is.fMult = fTrue;
  1220.   }
  1221.   if (us.fWheel) {
  1222.     if (is.fMult)
  1223.       PrintL2();
  1224.     ChartWheel();
  1225.     is.fMult = fTrue;
  1226.   }
  1227.   if (us.fGrid) {
  1228.     if (is.fMult)
  1229.       PrintL2();
  1230.     if (us.nRel > rcDual) {
  1231.       fCall = us.fSmartCusp; us.fSmartCusp = fFalse;
  1232.       if (!FCreateGrid(fFalse))
  1233.         return;
  1234.       us.fSmartCusp = fCall;
  1235.       not(fCall);
  1236.       ChartGrid();
  1237.       if (us.fGridConfig) {    /* If -g0 switch in effect, then  */
  1238.         PrintL();              /* display aspect configurations. */
  1239.         if (!fCall)
  1240.           FCreateGrid(fFalse);
  1241.         DisplayGrands();
  1242.       }
  1243.     } else {
  1244.  
  1245.       /* Do a relationship aspect grid between two charts if -r0 in effect. */
  1246.  
  1247.       fCall = us.fSmartCusp; us.fSmartCusp = fFalse;
  1248.       if (!FCreateGridRelation(us.fGridConfig))
  1249.         return;
  1250.       us.fSmartCusp = fCall;
  1251.       ChartGridRelation();
  1252.     }
  1253.     is.fMult = fTrue;
  1254.   }
  1255.   if (us.fAspList) {
  1256.     if (is.fMult)
  1257.       PrintL2();
  1258.     if (us.nRel > rcDual) {
  1259.       if (!fCall) {
  1260.         fCall = fTrue;
  1261.         if (!FCreateGrid(fFalse))
  1262.           return;
  1263.       }
  1264.       ChartAspect();
  1265.     } else {
  1266.       if (!FCreateGridRelation(fFalse))
  1267.         return;
  1268.       ChartAspectRelation();
  1269.     }
  1270.     is.fMult = fTrue;
  1271.   }
  1272.   if (us.fMidpoint) {
  1273.     if (is.fMult)
  1274.       PrintL2();
  1275.     if (us.nRel > rcDual) {
  1276.       if (!fCall) {
  1277.         if (!FCreateGrid(fFalse))
  1278.           return;
  1279.       }
  1280.       ChartMidpoint();
  1281.     } else {
  1282.       if (!FCreateGridRelation(fTrue))
  1283.         return;
  1284.       ChartMidpointRelation();
  1285.     }
  1286.     is.fMult = fTrue;
  1287.   }
  1288.   if (us.fHorizon) {
  1289.     if (is.fMult)
  1290.       PrintL2();
  1291.     if (us.fHorizonSearch)
  1292.       ChartInDayHorizon();
  1293.     else
  1294.       ChartHorizon();
  1295.     is.fMult = fTrue;
  1296.   }
  1297.   if (us.fOrbit) {
  1298.     if (is.fMult)
  1299.       PrintL2();
  1300.     ChartOrbit();
  1301.     is.fMult = fTrue;
  1302.   }
  1303.   if (us.fInfluence) {
  1304.     if (is.fMult)
  1305.       PrintL2();
  1306.     ChartInfluence();
  1307.     is.fMult = fTrue;
  1308.   }
  1309.   if (us.fAstroGraph) {
  1310.     if (is.fMult)
  1311.       PrintL2();
  1312.     ChartAstroGraph();
  1313.     is.fMult = fTrue;
  1314.   }
  1315.   if (us.fCalendar) {
  1316.     if (is.fMult)
  1317.       PrintL2();
  1318.     if (us.fCalendarYear)
  1319.       ChartCalendarYear();
  1320.     else
  1321.       ChartCalendarMonth();
  1322.     is.fMult = fTrue;
  1323.   }
  1324.   if (us.fInDay) {
  1325.     if (is.fMult)
  1326.       PrintL2();
  1327.     ChartInDaySearch(fProg);
  1328.     is.fMult = fTrue;
  1329.   }
  1330.   if (us.fInDayInf) {
  1331.     if (is.fMult)
  1332.       PrintL2();
  1333.     ChartInDayInfluence();
  1334.     is.fMult = fTrue;
  1335.   }
  1336.   if (us.fEphemeris) {
  1337.     if (is.fMult)
  1338.       PrintL2();
  1339.     ChartEphemeris();
  1340.     is.fMult = fTrue;
  1341.   }
  1342.   if (us.fTransit) {
  1343.     if (is.fMult)
  1344.       PrintL2();
  1345.     ChartTransitSearch(fProg);
  1346.     is.fMult = fTrue;
  1347.   }
  1348.   if (us.fTransitInf) {
  1349.     if (is.fMult)
  1350.       PrintL2();
  1351.     ChartTransitInfluence(fProg);
  1352.     is.fMult = fTrue;
  1353.   }
  1354. #ifdef ARABIC
  1355.   if (us.nArabic) {
  1356.     if (is.fMult)
  1357.       PrintL2();
  1358.     DisplayArabic();
  1359.     is.fMult = fTrue;
  1360.   }
  1361. #endif
  1362.  
  1363.   if (!is.fMult) {          /* Assume the -v chart if user */
  1364.     us.fListing = fTrue;    /* didn't indicate anything.   */
  1365.     PrintChart(fProg);
  1366.     is.fMult = fTrue;
  1367.   }
  1368. }
  1369.  
  1370. /* charts1.c */
  1371.